#include "expTable.h"
#include <sstream>		// Need gcc 3.0 or better
#include <cstring>
#include <algorithm>
expTable::expTable(void)
{
	//0xC0000000
	std::vector<unsigned int>& vec = expressionTable["r280"];
	vec.push_back(0xC0000000);
	std::vector<unsigned int>& vec2 = expressionTable["r290"];
	vec2.push_back(0xC0000000);
	count["r28"] = 1;
	stack["r28"] = 0;

	count["r29"] = 1;
	stack["r29"] = 0;
}


expTable::~expTable(void)
{
}

int expTable::getCount(std::string key){
	return count[key];
}
void expTable::setCount(std::string key, unsigned int value){
	count[key] = value;
}
int expTable::getStack(std::string key){
	return stack[key];
}
void expTable::setStack(std::string key, unsigned int value){
	stack[key] = value;
}

void expTable::addExpression(std::string key, unsigned int value){
	expressionTable[key].push_back(value);
}

std::vector<unsigned int> expTable::getExpression(std::string key){
	return expressionTable[key];
}


std::vector<unsigned int> expTable::lookupOriAddr(std::string key){
	std::ostringstream st;
	st << key << getStack(key);
	std::string newKey = st.str();
	return originalAddr[newKey];
}

std::vector<unsigned int> expTable::lookup(std::string key){
	std::ostringstream st;
	st << key << getStack(key);
	std::string newKey = st.str();
	return expressionTable[newKey];
}

void expTable::addNewExp(std::string key, unsigned int value){
	std::ostringstream st;
	st << key << (getCount(key));
	std::string newKey = st.str();
	std::vector<unsigned int> expvector = getExpression(newKey);
	std::vector<unsigned int>::iterator result = find( expvector.begin( ),expvector.end( ), value );
	if(result == expvector.end( )){
		addExpression(newKey, value);
	}
	setStack(key, getCount(key));
}

void expTable::addNewOriginalAddr(std::string key, unsigned int value){
	std::ostringstream st;
	st << key << (getCount(key));
	std::string newKey = st.str();
	std::vector<unsigned int> expvector = originalAddr[newKey];
	std::vector<unsigned int>::iterator result = find( expvector.begin( ),expvector.end( ), value );
	if(result == expvector.end( )){
		originalAddr[newKey].push_back(value);
	}
}

void expTable::print(std::ostream& os){
	std::map<std::string, std::vector<unsigned int> >::const_iterator
		map_it = expressionTable.begin();
	os << "\nexpression table: \n";
	while (map_it != expressionTable.end()) {
		std::vector<unsigned int>::const_iterator vecit = map_it->second.begin();
		while(vecit != map_it->second.end()){
			os << map_it->first << " = "
				<< std::hex << *vecit << " " << "\n";
			vecit ++;
		}
		++map_it; // increment iterator to denote the next element
	}

	std::map<std::string, std::vector<unsigned int> >::const_iterator
		ori_addr_map_it = originalAddr.begin();
	os << "\noriginal addr table: \n";
	while (ori_addr_map_it != originalAddr.end()) {
		std::vector<unsigned int>::const_iterator vecit = ori_addr_map_it->second.begin();
		while(vecit != ori_addr_map_it->second.end()){
			os << ori_addr_map_it->first << " = "
				<< std::hex << *vecit << " " << "\n";
			vecit ++;
		}
		++ori_addr_map_it; // increment iterator to denote the next element
	}

	os << "\ncount: \n";
	std::map<std::string, unsigned int>::const_iterator countit = count.begin();
	while(countit != count.end()){
		os << countit->first << " = " << countit->second << "\n";
		countit ++;
	}

	os << "\nstack: \n";
	std::map<std::string, unsigned int>::const_iterator stackit = stack.begin();
	while(stackit != stack.end()){
		os << stackit->first << " = " << stackit->second << "\n";
		stackit ++;
	}
}



void expTable::addBBToStack(unsigned int addr){
	this->bbstack.push_back(addr);
}
std::vector<unsigned int> expTable::getBBStack(){
	return this->bbstack;
}
void expTable::resumeBBStack(std::vector<unsigned int> bs){
	this->bbstack = bs;
}
bool expTable::isInBBStack(unsigned int addr){
	for(int i = 0;i < bbstack.size(); i++){
		if(addr == bbstack[i])
			return true;
	}
	return false;
}